package pfc.mensaje;


import java.io.File;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.lang.SecurityException;
import java.util.Vector;

import pfc.Constantes;
import pfc.Conversacion;
import pfc.Usuario;

/**
* Implementa el mensaje que adjunta un fichero.
* @author Gabriel Reus Rodríguez
* @version 1.0, 06/11/2010
*/

public class Fichero extends Mensaje
{

	/**
	*Almacena el contenido del fichero
	*/
	private Vector<Byte> bytes;
	/**
	*Nombre del fichero
	*/
	private String nombre;

	/**
	 * Variable necesaria para evitar el warning al compilar ya que debido a la herencia es una clase Serializable.
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * Constructor.	
	 */
	public Fichero(String grupo)
	{

		super(grupo,Constantes.MENSAJE_TIPO_FICHERO);
		Vector<Byte> v_byte= new Vector<Byte>();
	}

	public Fichero(String grupo,Conversacion conv,Usuario emisor)
	{

		super(grupo,Constantes.MENSAJE_TIPO_FICHERO,conv,emisor);
		Vector<Byte> v_byte= new Vector<Byte>();
	}

	/**
	 * Obtiene los bytes del fichero.   
	 */

	public Vector getBytes()
	{
		return this.bytes;
	}

	/**
	 * Obtiene el nombre del fichero.   
	 */
	public String getNombre()
	{
		return this.nombre;
	}

	/**
	 * Lee el fichero del disco y lo almacena en memoria siempre y cuando no ocupe más de un límite especificado en bytes por la variable MENSAJE_TAMANO_MAXIMO_FICHERO de la clase Constantes. 
	 * Una vez hecho puede enviarse a otro usuario.
	 */
	public void obtenFichero(String ruta) throws Exception
	{
	//Obtiene el fichero que le pasamos por parametro.


		File fichero;	
		try
		{
			fichero = new File(ruta);
			//Compruebo si el fichero que le he pasado existe.
			if(!fichero.exists())
			{
				//El fichero no existe por lo que lanzo la excepcion.
				throw new Exception("Error al leer el fichero"+ruta+", no existe");
			}
			//Compruebo que tengo permisos para leer el fichero.
			if(!fichero.canRead())
			{
				throw new Exception("Error, no tienes los permisos necesarios para leer el fichero  seleccionado");
			}
			//Compruebo que se ha pasado un fichero y no un directorio.
			if(!fichero.isFile())
			{
				//Lo que le pasamos por argumento NO es un fichero.
				throw new Exception("Error, la ruta indicada no es un fichero válido para enviar");
			}
			//Obtengo la longitud del fichero.
			if (fichero.length() > Constantes.MENSAJE_TAMANO_MAXIMO_FICHERO)
			{
				throw new Exception("Error, el fichero "+ruta+" pesa "+fichero.length()+" y es más del máximo permitido por la aplicación:  "+Constantes.MENSAJE_TAMANO_MAXIMO_FICHERO+" bytes");
			}
		}
		catch(NullPointerException e)
		{
			throw new Exception("Error: El fichero es incorrecto: "+ruta);
		}
		catch(Exception e)
		{
			throw e;
		}
		
		//Procedo a leer el fichero
		FileInputStream fileInput;
		BufferedInputStream bufferedInput;
		try
		{
			fileInput = new FileInputStream(ruta);
			bufferedInput = new BufferedInputStream(fileInput);
		}
		catch(FileNotFoundException e)
		{
			throw new Exception("Error al crear el FileInputStream y el BufferedInputStream");
		}
		catch(SecurityException e)
		{
			throw new Exception("Error al crear el FileInputStream y el BufferedInputStream");
		}
		byte bytes[] = new byte[1];
		int leidos=0;
		Vector<Byte> v_byte= new Vector<Byte>();
		//Leo el primer byte
		try
		{
			leidos=bufferedInput.read(bytes);
			v_byte.addElement(new Byte(bytes[0]));
			//Itero en el bucle.
			while (leidos > 0)
			{
				leidos=bufferedInput.read(bytes);
				v_byte.addElement(new Byte(bytes[0]));
			}
		}
		catch(IOException e)
		{
			//Error en la lectura del fichero por lo que vacio el vector de bytes, cierro los buffers y ficheros y lanzo la excepción.
			v_byte.clear();
			throw new Exception("Error al leer el fichero "+ruta);
		}
		catch(UnsupportedOperationException e)
		{
			throw new Exception ("UnsupportedOperation exception");
		}
		catch(ClassCastException e)
		{
			throw new Exception ("ClassCast exception");
		}
		catch(NullPointerException e)
		{
			throw new Exception ("NullPointer exception");
		}
		catch(IllegalArgumentException e)
		{
			throw new Exception ("IllegalArgument  exception");
		}
		finally
		{
			bufferedInput.close();
			fileInput.close();
		}

		//Guardo en la clase el contenido del fichero.
		this.bytes=v_byte;

		//Obtengo el nombre del fichero y lo almaceno.
		this.nombre=fichero.getName();

	}
	/**
	 * Guarda el fichero que está en memoria en la carpeta que le indiquemos con el nombre de fichero original. 
	 * Si ya existe un fichero con ese nombre se sobreescribe.
	 */
	public void guardaFichero(String carpeta) throws Exception
	{
		//Guarda el contenido del fichero almancenado en bytes.
		File fichero;
		try
		{
			fichero= new File(carpeta+this.nombre);

			//Compruebo si la carpeta existe
			File directorio= new File(carpeta);
			if(!directorio.exists())
			{
				throw new Exception("La carpeta destino no existe: "+carpeta);
			}

			//Compruebo que se ha pasado un fichero y no un directorio.
			if(!directorio.isDirectory())
			{
				//Lo que le pasamos por argumento NO es un fichero.
				throw new Exception("Error, la ruta indicada no es un directorio válido");
			}

			//Compruebo que tengo permisos para escribir el fichero.
			if(!directorio.canWrite())
			{
				throw new Exception("Error, no tienes los permisos necesarios para leer el fichero  seleccionado");
			}

			//Compruebo si fichero existe.
			if(fichero.exists())
			{
				//El fichero existe por lo que lo borro y continuo.
				try
				{
					fichero.delete();
				}
				catch(SecurityException e)
				{
					throw new Exception("El fichero ya existe y no es posible sobreescribirlo.");
				}
			}


		}
		catch(NullPointerException e)
		{
			throw new Exception("Error: La carpeta destino es incorrecta: "+carpeta+this.nombre);
		}
		catch(Exception e)
		{
			throw e;
		}

		//Creo el fichero y muevo el contenido.
			FileOutputStream fileOutput= null;
			BufferedOutputStream bufferedOutput= null;
		try
		{
			fichero.createNewFile();
			// Se abre el fichero donde se hará la copia
			fileOutput = new FileOutputStream (carpeta+this.nombre);
			bufferedOutput = new BufferedOutputStream(fileOutput);
			while (!this.bytes.isEmpty())
			{
				Byte b= this.bytes.firstElement();
				byte array[]= new byte[1];
				array[0]=b.byteValue();
				bufferedOutput.write(array);
				this.bytes.remove(0);
			}
			bufferedOutput.close();
			fileOutput.close();

		}
		catch(IOException e)
		{
			if(bufferedOutput == null)
			{
				bufferedOutput.close();
			}
			if(fileOutput == null)
			{
				fileOutput.close();
			}
			throw new Exception("Error al crear el fichero: "+carpeta+this.nombre);
		}
		catch(SecurityException e)
		{
			if(bufferedOutput == null)
			{
				bufferedOutput.close();
			}
			if(fileOutput == null)
			{
				fileOutput.close();
			}
			throw new Exception("Error, no tienes suficientes permisos en la carpeta: "+carpeta);
		}
		this.vaciaBytes();
		
	}

	/**
	 * Elimina de la memoria el fichero almacenado.
	 */
	private void vaciaBytes()
	{
		//Vacia el vector de bytes correspondiente a los datos del fichero
		this.bytes.clear();
	}


}
